#include "RingRequest.h"

#include <stdlib.h>
#include <sstream>
#include <stdio.h>

#include <Poco/DOM/Document.h>
#include <Poco/DOM/NodeIterator.h>
#include <Poco/Base64Encoder.h>
#include <Poco/Base64Decoder.h>
#include <Poco/StreamCopier.h>
#include "misc/Interface.h"
#include "misc/Debug.h"
#include "RingReply.h"
#include "RingDeny.h"
#include "nameserver/NameServer.h"
/*********************************************************/
void RingRequest::execute()
{
	NameServer& ns = NameServer::Instance();
	Interface& ui = Interface::Instance();

	// Build the reply message
	ns.mutex.lock();
	bool found = false;
	for ( unsigned int i = 0; i<ns.rings.size(); i++ ) {
		if ( ns.rings[i].getName() == name ) {
			// Get the node with the lowest load & increment it's load by 1 client
			std::string node = ns.rings[i].addClient(addr.toString());

			// Build a ring reply message & send it to the client
			RingReply	rRep;
			rRep.setHost(node);
			ns.sendTo(&rRep, addr.toString());
			
			// Report the ringrequest to the interface
			ui << "Client: " << addr.toString() << " requested ring: " << name << "@" << node << std::endl;
			ui.flush();
			found = true;
			break;
		}
	}

	if ( !found ) {
		ui << "Client: " << addr.toString() << " requested non existing ring: " << name << std::endl;
		ui.flush();
		
		// Build the RingDeny message and send it to the client
		RingDeny	deny;
		deny.setName(name);
		ns.sendTo(&deny, addr.toString());
	}
	
	ns.mutex.unlock();

	// Send an ack
	ack();
}
/*********************************************************/
std::string RingRequest::serialize() const
{
	NameServer& ns = NameServer::Instance();
	std::ostringstream		ostr;
	id = ns.getID();

	ostr << "<GS id='" << id << "'>";
	ostr << "<RingRequest>" << name << "</RingRequest>";
	ostr << "</GS>";

	return( ostr.str() );
}
/*********************************************************/
void RingRequest::deserialize(Poco::XML::NodeIterator& it)
{
	Poco::XML::Node* node = it.previousNode();
	name = node->innerText();
}
/*********************************************************/
void RingRequest::setRingName(const std::string& n)
{
	name = n;
}
/*********************************************************/
std::string RingRequest::getRingName() const
{
	return name;
}
/*********************************************************/
